#include "OgreRefAppSoccerTeamOwnedStates.h"
#include "OgreRefAppConstants.h"
#include "OgreRefAppSoccerPitch.h"
#include "OgreRefAppPlayerBase.h"

#define __DEBUGON__


namespace OgreRefApp
{

    void ChangePlayerHomeRegions(SoccerTeam* team, const int NewRegions[TeamSize])
    {
        std::vector<PlayerBase*>::const_iterator it = team->Members().begin();



        int plyr=0;
        for (it; it != team->Members().end(); ++it)
        {

            (*it)->SetHomeRegion( team->Pitch()->getRegionFromIndex(NewRegions[plyr]));
            plyr = plyr+1;

        }

    }

//************************************************************************ ATTACKING

    Attacking* Attacking::Instance()
    {
        static Attacking instance;

        return &instance;
    }


    void Attacking::Enter(SoccerTeam* team)
    {

        //these define the home regions for this state of each of the players
        const int BlueRegions[TeamSize] = {1,6,4,12,14};
        const int RedRegions[TeamSize] = {16,9,13,3,5};

        //set up the player's home regions
        if (team->Color() == SoccerTeam::blue)
        {
            ChangePlayerHomeRegions(team, BlueRegions);
        }
        else
        {
            ChangePlayerHomeRegions(team, RedRegions);
        }

        //if a player is in either the Wait or ReturnToHomeRegion states, its
        //steering target must be updated to that of its new home region to enable
        //it to move into the correct position.
        team->UpdateTargetsOfWaitingPlayers();
    }


    void Attacking::Execute(SoccerTeam* team)
    {
        //if this team is no longer in control change states
        if (!team->InControl())
        {
            team->GetFSM()->ChangeState(Defending::Instance());
            return;
        }

        //calculate the best position for any supporting attacker to move to
        team->DetermineBestSupportingPosition();
    }

    void Attacking::Exit(SoccerTeam* team)
    {
        //there is no supporting player for defense
        team->SetSupportingPlayer(NULL);
    }



//************************************************************************ DEFENDING

    Defending* Defending::Instance()
    {
        static Defending instance;

        return &instance;
    }

    void Defending::Enter(SoccerTeam* team)
    {



        //these define the home regions for this state of each of the players
        const int BlueRegions[TeamSize] = {1,3,5,6,8};
        const int RedRegions[TeamSize] = {16,12,14,9,11};

        //set up the player's home regions
        if (team->Color() == SoccerTeam::blue)
        {

            ChangePlayerHomeRegions(team, BlueRegions);
        }
        else
        {

            ChangePlayerHomeRegions(team, RedRegions);
        }


        //if a player is in either the Wait or ReturnToHomeRegion states, its
        //steering target must be updated to that of its new home region
        team->UpdateTargetsOfWaitingPlayers();
    }

    void Defending::Execute(SoccerTeam* team)
    {

        //if in control change states
        if (team->InControl())
        {
            team->GetFSM()->ChangeState(Attacking::Instance());
            return;
        }

    }


    void Defending::Exit(SoccerTeam* team){}



//************************************************************************ KICKOFF
    PrepareForKickOff* PrepareForKickOff::Instance()
    {
        static PrepareForKickOff instance;

        return &instance;
    }

    void PrepareForKickOff::Enter(SoccerTeam* team)
    {
        //reset key player pointers
        team->SetControllingPlayer(NULL);
        team->SetSupportingPlayer(NULL);
        team->SetReceiver(NULL);
        team->SetPlayerClosestToBall(NULL);

        //send Msg_GoHome to each player.
        team->ReturnAllFieldPlayersToHome();
    }

    void PrepareForKickOff::Execute(SoccerTeam* team)
    {
                    std::cout << "PrepareForKickOff::Execute "<< std::endl;

        //if both teams in position, start the game
        if (team->AllPlayersAtHome() && team->Opponents()->AllPlayersAtHome())
        {
            team->GetFSM()->ChangeState(Defending::Instance());
        }
    }

    void PrepareForKickOff::Exit(SoccerTeam* team)
    {
        team->Pitch()->setGameOn();
    }

}
